import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
import 'package:flutter_hand_tracking_plugin/HandGestureRecognition.dart';
import 'package:flutter_hand_tracking_plugin/flutter_hand_tracking_plugin.dart';
import 'package:flutter_hand_tracking_plugin/gen/landmark.pb.dart';

void main() => runApp(MaterialApp(home: MyApp()));

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  HandTrackingViewController _controller;
  Gestures _gesture;

  Color _selectedColor = Colors.black;
  Color _pickerColor = Colors.black;
  double _opacity = 1.0;
  double _strokeWidth = 3.0;
  double _canvasHeight = 300;
  double _canvasWeight = 300;

  bool _showBottomList = false;
  List<DrawingPoints> _points = List();
  SelectedMode _selectedMode = SelectedMode.StrokeWidth;

  List<Color> _colors = [
    Colors.red,
    Colors.green,
    Colors.blue,
    Colors.amber,
    Colors.black
  ];

  void continueDraw(landmark) =>
      setState(() =>
          _points.add(DrawingPoints(
              points: Offset(
                  landmark.x * _canvasWeight, landmark.y * _canvasHeight),
              paint: Paint()
                ..strokeCap = StrokeCap.butt
                ..isAntiAlias = true
                ..color = _selectedColor.withOpacity(_opacity)
                ..strokeWidth = _strokeWidth)));

  void finishDraw() => setState(() => _points.add(null));

  void _onLandMarkStream(NormalizedLandmarkList landmarkList) {
    if (landmarkList.landmark != null && landmarkList.landmark.length != 0) {
      setState(() =>
      _gesture =
          HandGestureRecognition.handGestureRecognition(landmarkList.landmark));
      if (_gesture == Gestures.ONE)
        continueDraw(landmarkList.landmark[8]);
      else if (_points.length != 0) finishDraw();
    } else
      _gesture = null;
  }

  getColorList() {
    List<Widget> listWidget = List();
    for (Color color in _colors) {
      listWidget.add(colorCircle(color));
    }
    Widget colorPicker = GestureDetector(
      onTap: () {
        showDialog(
          context: context,
          builder: (context) {
            return AlertDialog(
              title: const Text('选择颜色'),
              content: SingleChildScrollView(
                child: ColorPicker(
                  pickerColor: _pickerColor,
                  onColorChanged: (color) => _pickerColor = color,
//                enableLabel: true,
                  pickerAreaHeightPercent: 0.8,
                ),
              ),
              actions: <Widget>[
                FlatButton(
                  child: const Text('保存'),
                  onPressed: () {
                    setState(() => _selectedColor = _pickerColor);
                    Navigator.of(context).pop();
                  },
                ),
              ],
            );
          },
        );
      },
      child: ClipOval(
        child: Container(
          padding: const EdgeInsets.only(bottom: 16.0),
          height: 36,
          width: 36,
          decoration: BoxDecoration(
              gradient: LinearGradient(
                colors: [Colors.red, Colors.green, Colors.blue],
                begin: Alignment.topLeft,
                end: Alignment.bottomRight,
              )),
        ),
      ),
    );
    listWidget.add(colorPicker);
    return listWidget;
  }

  Widget colorCircle(Color color) {
    return GestureDetector(
      onTap: () => setState(() => _selectedColor = color),
      child: ClipOval(
        child: Container(
          padding: const EdgeInsets.only(bottom: 16.0),
          height: 36,
          width: 36,
          color: color,
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Hand Tracking Example App'),
      ),
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            Container(
              height: 300,
              child: HandTrackingView(
                onViewCreated: (HandTrackingViewController c) =>
                    setState(() {
                      _controller = c;
                      if (_controller != null)
                        _controller.landMarksStream.listen(_onLandMarkStream);
                    }),
              ),
            ),
            _controller == null
                ? Text(
                "Please grant camera permissions and reopen the application.")
                : Column(
              children: <Widget>[
                Text(_gesture == null
                    ? "No hand landmarks."
                    : _gesture.toString()),
                CustomPaint(
                  size: Size(_canvasWeight, _canvasHeight),
                  painter: DrawingPainter(
                    pointsList: _points,
                  ),
                )
              ],
            )
          ],
        ),
      ),
      bottomNavigationBar: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Container(
          padding: const EdgeInsets.only(left: 8.0, right: 8.0),
          decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(50.0),
              color: Colors.greenAccent),
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    IconButton(
                      icon: Icon(Icons.album),
                      onPressed: () =>
                          setState(() {
                            if (_selectedMode == SelectedMode.StrokeWidth)
                              _showBottomList = !_showBottomList;
                            _selectedMode = SelectedMode.StrokeWidth;
                          }),
                    ),
                    IconButton(
                      icon: Icon(Icons.opacity),
                      onPressed: () =>
                          setState(() {
                            if (_selectedMode == SelectedMode.Opacity)
                              _showBottomList = !_showBottomList;
                            _selectedMode = SelectedMode.Opacity;
                          }),
                    ),
                    IconButton(
                      icon: Icon(Icons.color_lens),
                      onPressed: () =>
                          setState(() {
                            if (_selectedMode == SelectedMode.Color)
                              _showBottomList = !_showBottomList;
                            _selectedMode = SelectedMode.Color;
                          }),
                    ),
                    IconButton(
                      icon: Icon(Icons.clear),
                      onPressed: () =>
                          setState(() {
                            _showBottomList = false;
                            _points.clear();
                          }),
                    ),
                  ],
                ),
                Visibility(
                  child: (_selectedMode == SelectedMode.Color)
                      ? Row(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: getColorList(),
                  )
                      : Slider(
                      value: (_selectedMode == SelectedMode.StrokeWidth)
                          ? _strokeWidth
                          : _opacity,
                      max: (_selectedMode == SelectedMode.StrokeWidth)
                          ? 50.0
                          : 1.0,
                      min: 0.0,
                      onChanged: (val) {
                        setState(() {
                          if (_selectedMode == SelectedMode.StrokeWidth)
                            _strokeWidth = val;
                          else
                            _opacity = val;
                        });
                      }),
                  visible: _showBottomList,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class DrawingPainter extends CustomPainter {
  DrawingPainter({this.pointsList});

  List<DrawingPoints> pointsList;
  List<Offset> offsetPoints = List();

  @override
  void paint(Canvas canvas, Size size) {
    for (int i = 0; i < pointsList.length - 1; i++) {
      if (pointsList[i] != null && pointsList[i + 1] != null) {
        canvas.drawLine(pointsList[i].points, pointsList[i + 1].points,
            pointsList[i].paint);
      } else if (pointsList[i] != null && pointsList[i + 1] == null) {
        offsetPoints.clear();
        offsetPoints.add(pointsList[i].points);
        offsetPoints.add(Offset(
            pointsList[i].points.dx + 0.1, pointsList[i].points.dy + 0.1));
        canvas.drawPoints(PointMode.points, offsetPoints, pointsList[i].paint);
      }
    }
  }

  @override
  bool shouldRepaint(DrawingPainter oldDelegate) => true;
}

class DrawingPoints {
  Paint paint;
  Offset points;

  DrawingPoints({this.points, this.paint});
}

enum SelectedMode { StrokeWidth, Opacity, Color }
